import UIKit
import Down
import SnapKit

public protocol MarkdownContentViewDelegate: AnyObject {
    func markdownContentView(_ view: MarkdownContentView, didTapImage url: URL)
    func markdownContentView(_ view: MarkdownContentView, shouldHandleLink url: URL) -> Bool
    func markdownContentView(_ view: MarkdownContentView, didHandleLink url: URL)
    func markdownContentView(_ view: MarkdownContentView, failedToHandleLink url: URL, error: Error)
    func markdownContentView(_ view: MarkdownContentView, didTapCustomTag tag: String, attributes: [String: String], content: String)
    func markdownContentView(_ view: MarkdownContentView, didLoadImage image: UIImage, from url: URL)
    
    // 任务列表相关
    func markdownContentView(_ view: MarkdownContentView, didToggleTaskListItem index: Int)
    func markdownContentView(_ view: MarkdownContentView, isTaskListItemChecked index: Int) -> Bool
}

public extension MarkdownContentViewDelegate {
    func markdownContentView(_ view: MarkdownContentView, shouldHandleLink url: URL) -> Bool {
        return true // 默认允许打开所有链接
    }
    
    func markdownContentView(_ view: MarkdownContentView, didLoadImage image: UIImage, from url: URL) {
        // 默认实现为空
    }
    
    func markdownContentView(_ view: MarkdownContentView, didToggleTaskListItem index: Int) {
        // 默认实现为空
    }
    
    func markdownContentView(_ view: MarkdownContentView, isTaskListItemChecked index: Int) -> Bool {
        return false // 默认未选中
    }
}

public class MarkdownContentView: UIView, MarkdownContentViewDelegate {
    public func markdownContentView(_ view: MarkdownContentView, didTapImage url: URL) {
        delegate?.markdownContentView(self, didTapImage: url)
    }
    
    public func markdownContentView(_ view: MarkdownContentView, shouldHandleLink url: URL) -> Bool {
        return delegate?.markdownContentView(self, shouldHandleLink: url) ?? true
    }
    
    public func markdownContentView(_ view: MarkdownContentView, didHandleLink url: URL) {
        delegate?.markdownContentView(self, didHandleLink: url)
    }
    
    public func markdownContentView(_ view: MarkdownContentView, failedToHandleLink url: URL, error: Error) {
        delegate?.markdownContentView(self, failedToHandleLink: url, error: error)
    }
    
    public func markdownContentView(_ view: MarkdownContentView, didTapCustomTag tag: String, attributes: [String: String], content: String) {
        delegate?.markdownContentView(self, didTapCustomTag: tag, attributes: attributes, content: content)
    }
    
    public func markdownContentView(_ view: MarkdownContentView, didLoadImage image: UIImage, from url: URL) {
        delegate?.markdownContentView(self, didLoadImage: image, from: url)
    }
    
    public func markdownContentView(_ view: MarkdownContentView, didToggleTaskListItem index: Int) {
        taskListManager.toggleItem(index)
        delegate?.markdownContentView(self, didToggleTaskListItem: index)
        reloadData()
    }
    
    public func markdownContentView(_ view: MarkdownContentView, isTaskListItemChecked index: Int) -> Bool {
        return taskListManager.isItemChecked(index)
    }
    
    public weak var delegate: MarkdownContentViewDelegate?
    
    private let customTagHandler: CustomTagHandler = {
        let handler = CustomTagHandler()
        return handler
    }()
    
    private let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.showsVerticalScrollIndicator = true
        scrollView.showsHorizontalScrollIndicator = false
        return scrollView
    }()
    
    private lazy var stackView: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.spacing = 8
        stack.alignment = .fill
        stack.distribution = .fill
        stack.isUserInteractionEnabled = true
        return stack
    }()
    
    private lazy var contentView: UITextView = {
        let textView = UITextView()
        textView.isEditable = false
        textView.isScrollEnabled = false
        textView.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
        textView.backgroundColor = .clear
        textView.delegate = self
        textView.linkTextAttributes = [
            .foregroundColor: theme.link.defaultColors.textColor,
            .underlineStyle: NSUnderlineStyle.single.rawValue
        ]
        return textView
    }()
    
    public var theme: MarkdownTheme = .light {
        didSet {
            updateThemeAppearance()
        }
    }
    
    public var imageBaseURL: URL?
    
    private let linkHandler = LinkHandler.shared
    
    public var codeBlockStyle: CodeBlockStyle = CodeBlockStyle.light {
        didSet {
            updateCodeBlockAppearance()
        }
    }
    
    public func updateCodeBlockStyle(_ style: CodeBlockStyle) {
        self.codeBlockStyle = style
        reloadData()
    }
    
    private func updateCodeBlockAppearance() {
        scrollView.subviews.forEach { view in
            if let codeBlock = view as? CodeBlockView {
                codeBlock.style = codeBlockStyle
            }
        }
    }
    
    public func reloadData() {
        if let markdownText = currentMarkdownText {
            render(markdownText)
        }
    }
    
    private var currentMarkdownText: String?
    
    private var configuration: MarkdownConfiguration
    
    public init(frame: CGRect = .zero, configuration: MarkdownConfiguration = MarkdownConfiguration()) {
        self.configuration = configuration
        super.init(frame: frame)
        setupUI()
        setupLinkHandler()
        setupCustomTagHandler()
    }
    
    required init?(coder: NSCoder) {
        self.configuration = MarkdownConfiguration()
        super.init(coder: coder)
        setupUI()
        setupLinkHandler()
        setupCustomTagHandler()
    }
    
    private func setupUI() {
        backgroundColor = theme.base.backgroundColor
        isUserInteractionEnabled = true
        
        addSubview(scrollView)
        scrollView.isUserInteractionEnabled = true
        
        scrollView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        scrollView.addSubview(stackView)
        stackView.isUserInteractionEnabled = true
        
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16))
            make.width.equalTo(scrollView.snp.width).offset(-32)
        }
        
        customTagHandler.delegate = self
    }
    
    @objc
    func test() {
        print("test --- ")
    }
    
    private func setupLinkHandler() {
        linkHandler.delegate = self
    }
    
    private func setupCustomTagHandler() {
        customTagHandler.delegate = self
    }
    
    private func updateThemeAppearance() {
        backgroundColor = theme.base.backgroundColor
        contentView.textColor = theme.base.textColor
        contentView.linkTextAttributes = [
            .foregroundColor: theme.link.customColors.textColor,
            .underlineStyle: NSUnderlineStyle.single.rawValue
        ]
    }
    
    public func render(_ markdown: String, imageBaseURL: URL? = nil) {
        self.currentMarkdownText = markdown
        self.imageBaseURL = imageBaseURL
        layoutIfNeeded()
        
        do {
            let down = Down(markdownString: markdown)
            let ast = try down.toAST()
            
            let visitor = MarkdownASTVisitor(
                containerWidth: bounds.width - 32,
                theme: theme,
                imageBaseURL: imageBaseURL,
                codeBlockStyle: codeBlockStyle,
                delegate: self,
                contentView: self
            )
            visitor.customTagHandler = customTagHandler
            stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
            
            if let contentStack = visitor.visit(ast.wrap() as! Document) {
                stackView.addArrangedSubview(contentStack)
            }
            
        } catch {
            print("Error parsing markdown: \(error)")
        }
    }
    
    public func updateTheme(_ theme: MarkdownTheme) {
        self.theme = theme
    }
    
    public func registerCustomHTMLNodeView(
        forTag tag: String,
        className: String,
        builder: @escaping CustomViewBuilder
    ) {
        customTagHandler.registerCustomHTMLNodeView(
            forTag: tag,
            className: className,
            builder: builder
        )
    }
    
    private func setupCustomTags() {
        // 注册引用标签视图
        registerCustomHTMLNodeView(forTag: "a", className: "ncTag") { [weak self] attributes, content in
            let label = PaddingLabel()
            label.numberOfLines = 0
            label.text = content
            
            // 设置样式
            let blueColor = self?.getSystemColor(
                light: UIColor(red: 0, green: 122/255, blue: 1, alpha: 1),
                dark: UIColor(red: 10/255, green: 132/255, blue: 1, alpha: 1)
            ) ?? .systemBlue
            
            label.backgroundColor = blueColor.withAlphaComponent(0.1)
            label.textColor = blueColor
            label.font = .systemFont(ofSize: 16)
            label.layer.cornerRadius = 4
            label.layer.masksToBounds = true
            label.padding = UIEdgeInsets(top: 2, left: 4, bottom: 2, right: 4)
            
            return label
        }
        
        // 注册用户标签视图
        registerCustomHTMLNodeView(forTag: "a", className: "userTag") { [weak self] attributes, content in
            let label = PaddingLabel()
            label.numberOfLines = 0
            label.text = content
            
            // 设置样式
            let greenColor = self?.getSystemColor(
                light: UIColor(red: 20/255, green: 160/255, blue: 60/255, alpha: 1),
                dark: UIColor(red: 30/255, green: 170/255, blue: 70/255, alpha: 1)
            ) ?? .systemGreen
            
            label.backgroundColor = greenColor.withAlphaComponent(0.1)
            label.textColor = greenColor
            label.font = .systemFont(ofSize: 16)
            label.layer.cornerRadius = 4
            label.layer.masksToBounds = true
            label.padding = UIEdgeInsets(top: 2, left: 4, bottom: 2, right: 4)
            
            return label
        }
    }
    
    private func getSystemColor(light: UIColor, dark: UIColor) -> UIColor {
        if #available(iOS 13.0, *) {
            return UIColor { traitCollection in
                return traitCollection.userInterfaceStyle == .dark ? dark : light
            }
        } else {
            return light
        }
    }
    
    private let taskListManager = TaskListManager()
    
    public func updateConfiguration(_ configuration: MarkdownConfiguration) {
        self.configuration = configuration
        // 重新应用配置到所有代码块视图
        reloadData()
    }
    
    // 在创建代码块视图时应用配置
    internal func createCodeBlockView(language: String?, code: String) -> CodeBlockView {
        let codeBlockView = CodeBlockView(language: language, code: code)
        
        // 应用配置
        codeBlockView.showHeader = configuration.codeBlockOptions.showHeader
        codeBlockView.showLanguageLabel = configuration.codeBlockOptions.showLanguageLabel
        codeBlockView.showCopyButton = configuration.codeBlockOptions.showCopyButton
        
        if let name = configuration.codeBlockOptions.languageDisplayName {
            codeBlockView.languageDisplayName = name
        }
        
        if let image = configuration.codeBlockOptions.copyButtonImage {
            codeBlockView.copyButtonImage = image
        }
        
        if let title = configuration.codeBlockOptions.copyButtonTitle {
            codeBlockView.copyButtonTitle = title
        }
        
        if let color = configuration.codeBlockOptions.headerBackgroundColor {
            codeBlockView.headerBackgroundColor = color
        }
        
        if let font = configuration.codeBlockOptions.languageLabelFont {
            codeBlockView.languageLabelFont = font
        }
        
        if let color = configuration.codeBlockOptions.languageLabelTextColor {
            codeBlockView.languageLabelTextColor = color
        }
        
        if let color = configuration.codeBlockOptions.copyButtonTintColor {
            codeBlockView.copyButtonTintColor = color
        }
        
        if let callback = configuration.codeBlockOptions.onCopy {
            codeBlockView.onCopy = callback
        }
        
        return codeBlockView
    }
}

extension MarkdownContentView: UITextViewDelegate {
    public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            
            if URL.scheme == "image" {
                self.delegate?.markdownContentView(self, didTapImage: URL)
            } else {
                self.linkHandler.handle(URL.absoluteString)
            }
        }
        return false
    }
    
    public func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        if let customAttachment = textAttachment as? CustomTagAttachment {
            let tagInfo = customAttachment.tagInfo
            delegate?.markdownContentView(self, didTapCustomTag: tagInfo.tag, attributes: tagInfo.attributes, content: tagInfo.content)
            return true
        }
        return true
    }
    
    public func textViewDidChangeSelection(_ textView: UITextView) {
        textView.selectedTextRange = nil
    }
}

extension MarkdownContentView: LinkHandlerDelegate {
    public func linkHandler(_ handler: LinkHandler, shouldHandle link: URL) -> Bool {
        return delegate?.markdownContentView(self, shouldHandleLink: link) ?? true
    }
    
    public func linkHandler(_ handler: LinkHandler, didHandle link: URL) {
        delegate?.markdownContentView(self, didHandleLink: link)
    }
    
    public func linkHandler(_ handler: LinkHandler, failedToHandle link: URL, error: Error) {
        delegate?.markdownContentView(self, failedToHandleLink: link, error: error)
    }
}

extension MarkdownContentView: CustomTagHandlerDelegate {
    public func customTag(didTap tag: String, attributes: [String: String], content: String) {
        delegate?.markdownContentView(self, didTapCustomTag: tag, attributes: attributes, content: content)
    }
} 
